#ifndef QOS_CPP_RT_TASK_HELPER
#define QOS_CPP_RT_TASK_HELPER

#include "task.hpp"
#include "timer.hpp"
#include "logger.hpp"
#include <cstdint>
#include <cstring>

namespace qOS {

    // Forward declaration
    class TlsfYoungAgeString;

    /**
     * @brief Real-time task data structure
     * @details Used to describe various parameters and constraints of real-time tasks
     */
    typedef struct {
        char        *name;                           // Task name
        int64_t      runtime;                        // Runtime (nanoseconds)
        int64_t      period;                         // Execution period (nanoseconds)
        int64_t      deadline;                       // Maximum allowed execution time (nanoseconds)
        uint32_t     action;                         // Task action identifier
        uint32_t     WaitForSyncSignal;              // Sync signal wait identifier
        char        *WaitForSyncZMQ;                 // ZMQ sync wait
        char        *WaitForSyncPaxos;               // Paxos sync wait
        uint64_t     token;                          // Security token
        int (*task_func)(uint64_t token, TlsfYoungAgeString& syncTaskData, void *userData);   // Task function pointer
    } RealTimeTask;

    /**
     * @brief Real-time task helper class
     * @details Provides automatic generation and management of real-time task arrays
     */
    class RealTimeTaskHelper {
    private:
        task *taskArray;                             // Task array
        RealTimeTask *rtTaskArray;                   // Real-time task configuration array
        size_t taskCount;                            // Task count
        bool initialized;                            // Initialization flag

        /**
         * @brief Convert nanoseconds to QuarkTS time unit
         * @param nanoseconds Nanosecond value
         * @return QuarkTS time unit
         */
        static duration_t nanosecondsToDuration(int64_t nanoseconds) {
            // 1 second = 1,000,000,000 nanoseconds
            // QuarkTS uses milliseconds as basic time unit
            return static_cast<duration_t>(nanoseconds / 1000000LL);
        }

        /**
         * @brief Generic task callback wrapper
         * @param e Event parameter
         * @param securityToken Security token
         * @param rtTask Real-time task configuration
         */
        static void taskCallbackWrapper(event_t e, uint64_t securityToken, RealTimeTask *rtTask) {
            if (e.firstCall()) {
                logger::out(logger::info) << "Real-time task started: " << rtTask->name;
                
                // Set task timing attributes
                TaskTimingAttr timingAttr;
                timingAttr.release_time = 0;
                timingAttr.deadline = static_cast<uint64_t>(rtTask->deadline / 1000LL);  // Convert to microseconds
                timingAttr.period = static_cast<uint64_t>(rtTask->period / 1000LL);      // Convert to microseconds
                timingAttr.wcet = static_cast<uint64_t>(rtTask->runtime / 1000LL);       // Convert to microseconds
                
                e.thisTask().setTimingAttributes(timingAttr);
            }

            // Security token verification
            if (securityToken != e.thisTask().GetSecurityToken()) {
                logger::out(logger::warning) << "Security token mismatch for task: " << rtTask->name;
                return;
            }

            // Call actual task function
            if (rtTask->task_func != nullptr) {
                // TlsfYoungAgeString implementation needed here
                // Temporarily using empty object or default implementation
                TlsfYoungAgeString syncTaskData;
                int result = rtTask->task_func(rtTask->token, syncTaskData, e.TaskData);
                
                if (result != 0) {
                    logger::out(logger::error) << "Task " << rtTask->name << " returned error: " << result;
                }
            }
        }

    public:
        /**
         * @brief Constructor
         */
        RealTimeTaskHelper() : taskArray(nullptr), rtTaskArray(nullptr), taskCount(0), initialized(false) {}

        /**
         * @brief Destructor
         */
        ~RealTimeTaskHelper() {
            cleanup();
        }

        /**
         * @brief Initialize real-time task array
         * @param rtTasks Real-time task configuration array
         * @param count Task count
         * @return Initialization success status
         */
        bool initialize(RealTimeTask rtTasks[], size_t count) {
            if (initialized) {
                logger::out(logger::warning) << "RealTimeTaskHelper already initialized";
                return false;
            }

            if (rtTasks == nullptr || count == 0) {
                logger::out(logger::error) << "Invalid parameters for RealTimeTaskHelper initialization";
                return false;
            }

            // Allocate memory
            taskArray = new task[count];
            if (taskArray == nullptr) {
                logger::out(logger::error) << "Failed to allocate memory for task array";
                return false;
            }

            rtTaskArray = new RealTimeTask[count];
            if (rtTaskArray == nullptr) {
                logger::out(logger::error) << "Failed to allocate memory for RT task array";
                delete[] taskArray;
                taskArray = nullptr;
                return false;
            }

            // Copy configuration data
            for (size_t i = 0;  i < count;  i++) {
                rtTaskArray[i] = rtTasks[i];
            }

            taskCount = count;
            initialized = true;

            logger::out(logger::info) << "RealTimeTaskHelper initialized with " << count << " tasks";
            return true;
        }

        /**
         * @brief Add real-time tasks to OS scheduler
         * @param os OS core instance
         * @return Addition success status
         */
        bool addTasksToScheduler(core &os) {
            if (!initialized) {
                logger::out(logger::error) << "RealTimeTaskHelper not initialized";
                return false;
            }

            for (size_t i = 0;  i < taskCount;  i++) {
                RealTimeTask &rtTask = rtTaskArray[i];
                
                if (rtTask.name == nullptr || rtTask.task_func == nullptr) {
                    logger::out(logger::error) << "Invalid task configuration at index " << i;
                    continue;
                }

                // Determine priority based on period
                priority_t priority = core::LOWEST_PRIORITY;
                if (rtTask.period <= 1000000LL) {      // Period <= 1ms, high priority
                    priority = core::HIGHEST_PRIORITY;
                }
                else if (rtTask.period <= 5000000LL) { // Period <= 5ms, medium priority
                    priority = core::MEDIUM_PRIORITY;
                }

                // Create lambda wrapper
                auto wrapper = [&rtTask](event_t e, uint64_t securityToken) {
                    taskCallbackWrapper(e, securityToken, &rtTask);
                };

                // Add to scheduler
                bool success = os.add(taskArray[i], wrapper, priority,
                                     nanosecondsToDuration(rtTask.period), 
                                     task::PERIODIC, 
                                     taskState::ENABLED_STATE);

                if (success) {
                    // Set task name
                    taskArray[i].setName(rtTask.name);
                    
                    // Set task data (pointing to RealTimeTask configuration)
                    taskArray[i].setData(&rtTask);
                    
                    logger::out(logger::info) << "Task added: " << rtTask.name 
                                             << " (period: " << rtTask.period << "ns, "
                                             << "deadline: " << rtTask.deadline << "ns)";
                } else {
                    logger::out(logger::error) << "Failed to add task: " << rtTask.name;
                }
            }

            return true;
        }

        /**
         * @brief Get task array
         * @return Task array pointer
         */
        task* getTaskArray() const {
            return taskArray;
        }

        /**
         * @brief Get task count
         * @return Task count
         */
        size_t getTaskCount() const {
            return taskCount;
        }

        /**
         * @brief Find task by name
         * @param name Task name
         * @return Task pointer, returns nullptr if not found
         */
        task* findTaskByName(const char *name) const {
            if (!initialized || name == nullptr) {
                return nullptr;
            }

            for (size_t i = 0;  i < taskCount;  i++) {
                if (rtTaskArray[i].name != nullptr && 
                    std::strcmp(rtTaskArray[i].name, name) == 0) {
                    return &taskArray[i];
                }
            }

            return nullptr;
        }

        /**
         * @brief Get real-time configuration of task
         * @param t Task pointer
         * @return Real-time task configuration pointer
         */
        RealTimeTask* getRealTimeTaskConfig(const task *t) const {
            if (!initialized || t == nullptr) {
                return nullptr;
            }

            for (size_t i = 0;  i < taskCount;  i++) {
                if (&taskArray[i] == t) {
                    return &rtTaskArray[i];
                }
            }

            return nullptr;
        }

        /**
         * @brief Clean up resources
         */
        void cleanup() {
            if (taskArray != nullptr) {
                delete[] taskArray;
                taskArray = nullptr;
            }
            
            if (rtTaskArray != nullptr) {
                delete[] rtTaskArray;
                rtTaskArray = nullptr;
            }
            
            taskCount = 0;
            initialized = false;
        }

        /**
         * @brief Check if initialized
         * @return Initialization status
         */
        bool isInitialized() const {
            return initialized;
        }
    };

    // Simplified implementation of TlsfYoungAgeString (placeholder)
    class TlsfYoungAgeString {
    private:
        char *data;
        size_t size;
        
    public:
        TlsfYoungAgeString() : data(nullptr), size(0) {}
        
        // Actual implementation can be added here as needed
        // Currently serves as placeholder class
    };

} // namespace qOS

#endif // QOS_CPP_RT_TASK_HELPER